﻿
package com.android.finaltracer.engine;

import java.util.ArrayList;

import android.content.Context;

import com.android.finaltracer.channel.ChannelProxy;
import com.android.finaltracer.model.SyncInfo;
import com.android.finaltracer.usermanage.FtTimer;

public class Sync {

    private EventNotify mEventNotify;

    private static final int SYNC_NULL = 1;// 1

    private static final int SYNC_WAIT_SYNC_CNF = SYNC_NULL + 1;// 2

    int state;

    private static Sync instance;

    private ChannelProxy mChannelProxy;

    private ArrayList<SyncTask> task;

    private SyncTask currentTask;

    private int retryCount = 0;
    private int maxRetryCount = 3;

    // 当控制多个手机的时候 得用hashmap
    private boolean isSlaveAlive;

    private Sync(Context context, EventNotify mEventNotify) {
        this.mEventNotify = mEventNotify;
        mChannelProxy = ChannelProxy.getInstance(context, this.mEventNotify);
        task = new ArrayList<SyncTask>();
        this.state = SYNC_NULL;
        isSlaveAlive = false;
    }

    public static Sync getInstance(Context context, EventNotify mEventNotify) {
        if (instance == null) {
            instance = new Sync(context, mEventNotify);
        }
        return instance;
    }

    public synchronized void startSync(String toPhone, int module) {
        task.add(new SyncTask(toPhone, module));
        onStart();
    }

    public synchronized void removeAllTask() {
        task.clear();
        state = SYNC_NULL;
    }

    public void remoteCnfSync(String from, SyncInfo si) {
        switch (si.getCommand()) {
            case SyncInfo.SYNC_HANDSHAKE_REQ:
                sendSync(
                        from,
                        new SyncInfo(SyncInfo.SYNC_HANDSHAKE_CNF, si.getModule(),
                                mEventNotify.getSpecifyPhoneStatus(from,
                                        si.getModule()), mChannelProxy.isAlive()));
                isSlaveAlive = true;
                break;
            case SyncInfo.SYNC_HANDSHAKE_CNF:
                // sync success
                // do sth.
                FtTimer.stopTimer(EngineService.MODULE_SYNC_TRACER, from);
                mEventNotify.onRemoteCnfSync(from, si.getModule(),
                        si.getPhoneStatus(), si.isAlive());
                onFinsh();
                break;
            default:
                break;
        }
    }

    // int command,int moule , int state ,boolean isAlive
    private void sendSync(String toPhoneNum, SyncInfo si) {
        mChannelProxy.send(toPhoneNum, si, ChannelProxy.CHANNEL_SMS);
        if (si.getCommand() == SyncInfo.SYNC_HANDSHAKE_REQ) {
            FtTimer.startTimer(EngineService.MODULE_SYNC_TRACER,
                    FtTimer.TIMER_ID_COMMAND_WAIT_SYNC_CNF, toPhoneNum);
            retryCount++;
        }
    }

    private synchronized void onStart() {
        if (state != SYNC_NULL) {
            return;
        }
        if (task.size() > 0) {
            currentTask = task.get(0);
            SyncInfo si = new SyncInfo(SyncInfo.SYNC_HANDSHAKE_REQ,
                    currentTask.getMoudle(),
                    mEventNotify.getSpecifyPhoneStatus(
                            currentTask.getToPhone(), currentTask.getMoudle()),
                    mChannelProxy.isAlive());
            sendSync(currentTask.getToPhone(), si);
            state = SYNC_WAIT_SYNC_CNF;
        }
    }

    private void onFinsh() {
        task.remove(0);
        clearRetryCount();
        state = SYNC_NULL;
        onStart();
    }

    public void onFailer(String from) {
        state = SYNC_NULL;
        onStart();
    }

    public boolean isSlaveAlive() {
        return isSlaveAlive;
    }

    public void setSlaveAlive(String phoneNum, boolean isSlaveAlive) {
        this.isSlaveAlive = isSlaveAlive;
    }

    private void clearRetryCount() {
        retryCount = 0;
    }

    public boolean isOutRetry() {
        return retryCount >= maxRetryCount;
    }

    public class SyncTask {
        private String toPhone;
        private int module;

        public SyncTask(String toPhone, int module) {
            super();
            this.module = module;
            this.toPhone = toPhone;
        }

        public int getMoudle() {
            return module;
        }

        public void setMoudle(int module) {
            this.module = module;
        }

        public String getToPhone() {
            return toPhone;
        }

        public void setToPhone(String toPhone) {
            this.toPhone = toPhone;
        }
    }
}
